﻿// Decompiled with JetBrains decompiler
// Type: MCM.LightInject.MostResolvableConstructorSelector
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;

#nullable disable
namespace MCM.LightInject
{
  [ExcludeFromCodeCoverage]
  internal class MostResolvableConstructorSelector : IConstructorSelector
  {
    private readonly Func<Type, string, bool> canGetInstance;
    private readonly bool enableOptionalArguments;

    public MostResolvableConstructorSelector(
      Func<Type, string, bool> canGetInstance,
      bool enableOptionalArguments)
    {
      this.canGetInstance = canGetInstance;
      this.enableOptionalArguments = enableOptionalArguments;
    }

    public MostResolvableConstructorSelector(Func<Type, string, bool> canGetInstance)
      : this(canGetInstance, false)
    {
    }

    public ConstructorInfo Execute(Type implementingType)
    {
      ConstructorInfo[] array = implementingType.GetTypeInfo().DeclaredConstructors.Where<ConstructorInfo>((Func<ConstructorInfo, bool>) (c => c.IsPublic && !c.IsStatic)).ToArray<ConstructorInfo>();
      if (array.Length == 0)
        throw new InvalidOperationException("Missing public constructor for Type: " + implementingType.FullName);
      if (array.Length == 1)
        return array[0];
      foreach (ConstructorInfo constructorInfo in (IEnumerable<ConstructorInfo>) ((IEnumerable<ConstructorInfo>) array).OrderByDescending<ConstructorInfo, int>((Func<ConstructorInfo, int>) (c => c.GetParameters().Length)))
      {
        if (this.CanCreateParameterDependencies((IEnumerable<ParameterInfo>) constructorInfo.GetParameters()))
          return constructorInfo;
      }
      throw new InvalidOperationException("No resolvable constructor found for Type: " + implementingType.FullName);
    }

    protected virtual string GetServiceName(ParameterInfo parameter) => parameter.Name;

    private bool CanCreateParameterDependencies(IEnumerable<ParameterInfo> parameters)
    {
      return parameters.All<ParameterInfo>(new Func<ParameterInfo, bool>(this.CanCreateParameterDependency));
    }

    private bool CanCreateParameterDependency(ParameterInfo parameterInfo)
    {
      return this.canGetInstance(parameterInfo.ParameterType, string.Empty) || this.canGetInstance(parameterInfo.ParameterType, this.GetServiceName(parameterInfo)) || parameterInfo.HasDefaultValue && this.enableOptionalArguments;
    }
  }
}
